#include <simulatorV1/lexer/lexer.h>
#include <simulatorV1/lexer/id.h>
#include <simulatorV1/lexer/num.h>
#include <simulatorV1/log/report.h>

Lexer::Lexer() {
    m_curIndex = 0;
    m_ch = ' ';
    m_keywords = std::make_unique<Keywords>();
}

void Lexer::loadBuffer(std::string buffer) {
    m_curIndex = 0;
    m_ch = ' ';
    m_buffer = buffer;
}

char Lexer::scanner() {
    u64 bufferSize = m_buffer.size();
    if (m_curIndex >= bufferSize) {
        return '\n';
    } else {
        return m_buffer[m_curIndex++];
    }
}

std::shared_ptr<Token> Lexer::tokenize() {

    // 忽略空白符
    while (m_ch == ' ' || m_ch == '\t') {
        m_ch = scanner();
    }

    // 到达命令末尾
    if (m_ch == '\n') {
        return std::make_shared<Token>(Tag::END);
    }

    // 标识符 关键字
    if ((m_ch >= 'a' && m_ch <= 'z') || (m_ch >= 'A' && m_ch <= 'Z')) {
        std::string name;
        do {
            name.push_back(m_ch);
            m_ch = scanner();
        } while ((m_ch >= 'a' && m_ch <= 'z') || (m_ch >= 'A' && m_ch <= 'Z') || (m_ch >= '0' && m_ch <= '9'));
        Tag tag = m_keywords->getTag(name);
        if (tag == Tag::ID) {
            return std::make_shared<Id>(name);
        } else {
            return std::make_shared<Token>(tag);
        }
    } else if (m_ch >= '0' && m_ch <= '9') {
        //数字
        u64 val = 0;
        if (m_ch != '0') {
            // 10进制
            do {
                val = val * 10 + m_ch - '0';
                m_ch = scanner();
            } while (m_ch >= '0' && m_ch <= '9');
        } else {
            //16进制
            m_ch = scanner();
            if (m_ch == 'x' || m_ch == 'X') {
                m_ch = scanner();
                if ((m_ch >= '0' && m_ch <= '9') || (m_ch >= 'A' && m_ch <= 'F') || (m_ch >= 'a' && m_ch <= 'f')) {
                    do {
                        val = val * 16 + m_ch;
                        if (m_ch >= '0' && m_ch <= '9') val -= '0';
                        else if (m_ch >= 'A' && m_ch <= 'F') val += 10 - 'A';
                        else if (m_ch >= 'a' && m_ch <= 'f') val += 10 - 'a';
                        m_ch = scanner();
                    } while (m_ch >= '0' && m_ch <= '9' || m_ch >= 'A' && m_ch <= 'F' || m_ch >= 'a' && m_ch <= 'f');
                } else {
                    fatalMacro("16进制数格式不正确");
                }
            }
        }
        return std::make_shared<Num>(val);
    } else if (m_ch == ',') {
        m_ch = scanner();
        return std::make_shared<Token>(Tag::COMMA);
    } else if (m_ch  == '(') {
        m_ch = scanner();
        return std::make_shared<Token>(Tag::LPAREN);
    } else if (m_ch  == ')') {
        m_ch = scanner();
        return std::make_shared<Token>(Tag::RPAREN);
    } else if (m_ch  == ';') {
        m_ch = scanner();
        return std::make_shared<Token>(Tag::SEMICOLON);
    } else {
        m_ch = scanner();
        return std::make_shared<Token>(Tag::UN_KNOWN);
    }
}